home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
threads
/
ThreadsSharedMemBSD.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-05
|
12KB
|
466 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* ThreadsSharedMemBSD.c
*
* Demers, December 5, 1990 8:38:35 am PST
*
*/
#include "xr/BasicTypes.h"
#include "xr/Threads.h"
#include "xr/ThreadsBackdoor.h"
#include "xr/ThreadsSharedMem.h"
#include "xr/ThreadsSharedMemPrivate.h"
#include "xr/ThreadsSharedMemBSDUtils.h"
#include "xr/ThreadsMsgPrivate.h"
#include "xr/Errno.h"
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h> /* for dbtob() below */
#define WARN_NOT_ISVTX 1
#define COUNT_FLUSHES 1
#if WARN_NOT_ISVTX
# define CHECK_NOT_ISVTX(test,fmt,x) \
{ if( test ) XR_WarnNotISVTX((fmt), (x)); }
static void
XR_WarnNotISVTX(fmt, x)
char *fmt;
int x;
{
XR_ConsoleMsg("WARNING: backing file sticky bit not set.\n\t");
if( fmt ) {
XR_ConsoleMsg(fmt, x);
XR_ConsoleMsg("\n");
}
}
#else
# define CHECK_NOT_ISVTX(test,fmt,x)
#endif
extern void bcopy(/* char *from, char *to, int nbytes */);
/*
* Directory and temp file name management ...
*/
#define LAST_DIRECTORY_TO_TRY 9
/*
* Initialization
*/
static char *
XR_SetShmTypeBSD(shmType)
char *shmType;
{
(void)XR_SharedMemBSDSetSwapDir(DEFAULT_SWAP_DIR, DI_NONE);
return NIL;
}
static char *
XR_SetShmArgBSD(shmArg)
char *shmArg;
{
if( (shmArg == NIL) || (shmArg[0] != '/') ) {
return "BSD shared memory swap directory not full pathname";
}
if( XR_SharedMemBSDSetSwapDir(shmArg, DI_NONE) != 0 ) {
return "BSD shared memory swap directory bad (too long?)";
}
return NIL;
}
static char *
XR_InitSharedMemBSD()
{
int i, fd, ans;
char fnBuf[FILE_NAME_BUF_SIZE];
(void)XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf), NIL, FI_NONE);
ans = access(fnBuf, (R_OK|X_OK) );
if( ans < 0 ) return("InitSharedMemBSD: can't access swap dir");
for( i = 0; ; i++ ) {
(void)XR_SharedMemBSDSetSwapDir(NIL, i);
ans = XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf),
FN_LOCK, FI_NONE );
if( ans < 0 ) {
(void)XR_SharedMemBSDSetSwapDir(NIL, DI_NONE);
XR_Panic("InitSharedMemBSD: lock file name err");
}
fd = open(fnBuf, O_CREAT|O_EXCL, 0600);
if( fd >= 0 ) {
(void)close(fd);
return NIL;
}
if( i >= LAST_DIRECTORY_TO_TRY ) {
(void)XR_SharedMemBSDSetSwapDir(NIL, DI_NONE);
return("InitSharedMemBSD: can't find unlocked swap subdir");
}
}
}
/*
* NOTE: the following had better be called while running on Unix stack,
* with no dependency on data or bss after return. This is delicate!
*/
static void
XR_CleanUpSharedMemBSD()
{
int i, ans, lans, dirIndex;
char fnBuf[FILE_NAME_BUF_SIZE];
char lfnBuf[FILE_NAME_BUF_SIZE];
(void)XR_SharedMemBSDGetSwapDir(NIL, 0, &dirIndex);
if( dirIndex == DI_NONE ) return;
for( i = 0; i < XR_maxThreads; i++ ) {
ans = XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf), FN_STACK, i);
if( ans >= 0 ) (void)truncate(fnBuf, 0);
}
ans = XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf),
FN_HEAP, FI_NONE );
if( ans >= 0 ) (void)truncate(fnBuf, 0);
ans = XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf),
FN_DATA, FI_NONE );
lans = XR_SharedMemBSDMkFileName(lfnBuf, (sizeof lfnBuf),
FN_LOCK, FI_NONE );
if( ans >= 0 ) (void)truncate(fnBuf, 0);
if( lans >= 0 ) (void)unlink(lfnBuf);
}
/*
* Shared data + bss
*/
static char *
XR_ShareMemInitialBSD(p)
XR_Pointer p;
{
int fd, ans, written;
unsigned bytes;
XR_Pointer mmapAns;
extern int end;
if( !XR_PAGE_ALIGNED(p) )
XR_Panic("ShareMemInitialBSD 0: not page-aligned");
bytes = XR_RoundToPage(
((unsigned)(&end)) - ((unsigned)(p)),
XR_ROUND_UP );
/* create temporary file */
ans = XR_SharedMemBSDGetBackingFile( FN_DATA, FI_NONE,
SETLEN_NOCHANGE, &fd );
if( ans < 0 ) {
return("ShareMemInitialBSD: can't create backing file");
}
CHECK_NOT_ISVTX((ans>0), FN_DATA, 0);
/* copy stuff into file */
written = 0;
while( written < bytes ) {
ans = write(fd, p+written, bytes-written);
if( ans <= 0 ) {
return("ShareMemInitialBSD: write error");
}
written += ans;
}
ans = ftruncate(fd, written);
if( ans < 0 ) {
return("ShareMemInitialBSD2: ftruncate error");
}
/* mmap the file */
mmapAns = (XR_Pointer)mmap(
p,
bytes,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_FIXED,
fd,
0 );
if( mmapAns != p ) {
return("ShareMemInitialBSD: mmap error");
}
/* close the file */
(void)close(fd);
return NIL;
}
/*
* "system memory"
*/
static char *
XR_InitSharedSysMemBSD(nBytes)
unsigned nBytes;
{
XR_Pointer a, mmapAns;
int fd, ans;
unsigned sysMemBytes = XR_RoundToPage(nBytes, XR_ROUND_UP);
a = XR_VMReserve(sysMemBytes);
XR_memInfo->mi_sysMemStart = a;
XR_memInfo->mi_sysMemFree = a;
XR_memInfo->mi_sysMemLimit = a + sysMemBytes;
ans = XR_SharedMemBSDGetBackingFile(FN_HEAP, FI_NONE,
XR_memInfo->mi_sysMemLimit, &fd);
if( ans < 0 ) {
return("InitSharedSysMemBSD: can't create backing file");
}
CHECK_NOT_ISVTX((ans>0), FN_HEAP, 0);
mmapAns = (XR_Pointer)mmap(
a,
sysMemBytes,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_FIXED,
fd,
a );
if( mmapAns != a ) {
return("InitSharedSysMemBSD: mmap error");
}
(void)close(fd);
return NIL;
}
#define XR_AllocSharedSysMemBSD NIL
/*
* Stacks
*/
static char *
XR_InitSharedStackMemBSD(maxStacks, totalBytes)
unsigned maxStacks;
unsigned totalBytes;
{
unsigned bytesToAllocate;
XR_Pointer a;
bytesToAllocate = XR_RoundToPage(
totalBytes+(2*maxStacks*XR_GetPageSize()),
XR_ROUND_UP );
a = XR_VMReserve(bytesToAllocate);
XR_memInfo->mi_maxStacks = maxStacks;
XR_memInfo->mi_stacksStart = a;
XR_memInfo->mi_stacksFree = a;
XR_memInfo->mi_stacksLimit = a + bytesToAllocate;
return NIL;
}
static XR_Pointer
XR_AllocSharedStackMemBSD(index, nBytes)
int index;
unsigned nBytes;
{
XR_Pointer protArea, newStk, newFree, mmapAns;
int fd, ans;
if( (index < 0) || (index >= XR_memInfo->mi_maxStacks) ) {
XR_Panic("AllocSharedStackMemBSD 0: too many stacks");
}
protArea = XR_ComputeAddress(XR_memInfo->mi_stacksFree, 0, XR_ROUND_UP);
newStk = XR_ComputeAddress(protArea, 1, XR_ROUND_UP);
nBytes = XR_RoundToPage(nBytes, XR_ROUND_UP);
newFree = XR_ComputeAddress(newStk, nBytes, XR_DONT_ROUND);
if( newFree > XR_memInfo->mi_stacksLimit ) {
XR_Panic("AllocSharedStackMemBSD 1: too many bytes");
}
ans = XR_SharedMemBSDGetBackingFile(
FN_STACK, index, nBytes, &fd );
if( ans < 0 ) {
XR_Panic("AllocSharedStackMemBSD 2: can't create backing file");
}
CHECK_NOT_ISVTX((ans>0), "stack file %d", index);
mmapAns = (XR_Pointer)mmap(
newStk,
nBytes,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_FIXED,
fd,
0 );
if( mmapAns != newStk ) {
XR_Panic("AllocSharedStackMemBSD 3: mmap error");
}
(void)close(fd);
XR_memInfo->mi_stacksFree = newFree;
return newStk;
}
#if COUNT_FLUSHES
static int XR_sharedMemBSDFlushIndex;
static int XR_sharedMemBSDFlushResult;
int XR_GetSharedMemBSDFlushIndex() { return XR_sharedMemBSDFlushIndex; }
int XR_GetSharedMemBSDFlushResult() { return XR_sharedMemBSDFlushResult; }
#endif
static int
XR_FlushSharedStackMemBSD(index, pLow, pHigh, minBytesToFlush, pBytesFlushed)
int index;
XR_Pointer pLow;
XR_Pointer pHigh;
int minBytesToFlush;
int *pBytesFlushed;
{
int nBytes, nBytesAllocated;
int ans;
char fnBuf[FILE_NAME_BUF_SIZE];
struct stat statBuf;
if( (index < 0) || (index >= XR_memInfo->mi_maxStacks) ) return (-EINVAL);
nBytes = ((char *)(pHigh)) - ((char *)(pLow));
if( nBytes < 0 ) return (-EINVAL);
ans = XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf), FN_STACK, index);
if( ans < 0 ) return (-ENAMETOOLONG);
ans = stat(fnBuf, &statBuf);
if( ans < 0 ) return (-XR_GetErrno());
nBytesAllocated = dbtob(statBuf.st_blocks);
# if COUNT_FLUSHES
XR_sharedMemBSDFlushIndex = index;
# endif
if( (nBytes > 0)
|| (nBytesAllocated < minBytesToFlush) ) {
if( pBytesFlushed != NIL ) *pBytesFlushed = 0;
# if COUNT_FLUSHES
XR_sharedMemBSDFlushResult = nBytesAllocated;
# endif
return (nBytesAllocated);
}
(void)truncate( fnBuf, 0 );
(void)truncate( fnBuf, statBuf.st_size );
if( pBytesFlushed != NIL ) *pBytesFlushed = nBytesAllocated;
# if COUNT_FLUSHES
XR_sharedMemBSDFlushResult = 0;
# endif
return (0);
}
/*
* Heap
*/
static XR_Pointer
XR_InitSharedHeapMemBSD(nBytes)
unsigned nBytes;
{
XR_Pointer heapAddr, mmapAns;
int fd, ans;
heapAddr = XR_VMReserve(nBytes);
XR_memInfo->mi_heapStart = XR_memInfo->mi_heapFree = heapAddr;
XR_memInfo->mi_heapLimit = XR_VMReserve(0);
ans = XR_SharedMemBSDGetBackingFile(FN_HEAP, FI_NONE, heapAddr, &fd);
if( ans < 0 ) return NIL;
CHECK_NOT_ISVTX((ans>0), FN_HEAP, 0);
mmapAns = (XR_Pointer)mmap(
heapAddr,
nBytes,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_FIXED,
fd,
heapAddr );
if( mmapAns != heapAddr ) return NIL;
(void)close(fd);
return heapAddr;
}
static int
XR_MapSharedHeapSegBSD(seg)
XR_Seg seg;
{
XR_Pointer newFree;
int ans;
char fnBuf[FILE_NAME_BUF_SIZE];
ans = XR_SharedMemBSDMkFileName(fnBuf, (sizeof fnBuf), FN_HEAP, FI_NONE);
if( ans < 0 ) return ans;
newFree = XR_ComputeAddress(seg->seg_addr, seg->seg_bytes, XR_DONT_ROUND);
ans = truncate(fnBuf, newFree);
if( ans < 0 ) return (-XR_GetErrno());
return 0;
}
#define XR_ApplyToSysMemBSD NIL
struct XR_ShmImplRep XR_shmImplRepBSD = {
/* shmType */ "bsd",
/* data */ NIL,
/* setShmType */ XR_SetShmTypeBSD,
/* setShmArg */ XR_SetShmArgBSD,
/* initSharedMem */ XR_InitSharedMemBSD,
/* cleanUpSharedMem */ XR_CleanUpSharedMemBSD,
/* shareMemInitial */ XR_ShareMemInitialBSD,
/* initSharedSysMem */ XR_InitSharedSysMemBSD,
/* allocSharedSysMem */ XR_AllocSharedSysMemBSD,
/* initSharedStackMem */ XR_InitSharedStackMemBSD,
/* allocSharedStackMem */ XR_AllocSharedStackMemBSD,
/* flushSharedStackMem */ XR_FlushSharedStackMemBSD,
/* initSharedHeapMem */ XR_InitSharedHeapMemBSD,
/* mapSharedHeapSeg */ XR_MapSharedHeapSegBSD,
/* applyToSysMem */ XR_ApplyToSysMemBSD
};